home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / aliaslib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-31  |  9.8 KB  |  339 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: aliaslib.c,v 5.9 1993/05/31 19:39:43 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.9 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: aliaslib.c,v $
  17.  * Revision 5.9  1993/05/31  19:39:43  syd
  18.  * Elm either failed to expand a group alias or crashed in strlen
  19.  * (called from do_expand_group()).
  20.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  21.  *
  22.  * Revision 5.8  1993/05/14  03:53:46  syd
  23.  * Fix wrong message being displayed and then overwritten
  24.  * for long aliases.
  25.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  26.  *
  27.  * Revision 5.7  1993/05/08  17:03:16  syd
  28.  * If there are local user names (account names) in the alias, they don't
  29.  * get fully expanded with a GCOS field like they do when you type an
  30.  * account name on the To line.
  31.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  32.  *
  33.  * Revision 5.6  1993/04/12  01:10:15  syd
  34.  * fix @aliasname sort problem
  35.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  36.  *
  37.  * Revision 5.5  1993/02/07  15:13:13  syd
  38.  * remove extra declaration of lseek, now in hdrs/defs.h
  39.  * From: Syd
  40.  *
  41.  * Revision 5.4  1993/01/20  03:02:19  syd
  42.  * Move string declarations to defs.h
  43.  * From: Syd
  44.  *
  45.  * Revision 5.3  1992/12/12  01:28:24  syd
  46.  * in do_get_alias().  abuf[] was under dimensioned.
  47.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  48.  *
  49.  * Revision 5.2  1992/10/11  01:21:17  syd
  50.  * 1. If firstname && lastname is null then copy aliasname into the
  51.  * personal name field (inside the ()'s) when creating an alias
  52.  * from the menu using the 'n' command.
  53.  *
  54.  * 2. Now if for some reason and alias has a null personal name field
  55.  * (the person hand edited aliases.text) the blank () is not printed
  56.  * as part of the address.  This actually cured another problem, where
  57.  * the To: field on the screen (when you hit 'm' on the alias menu)
  58.  * used to be blank, now the address shows up....
  59.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  60.  *
  61.  * Revision 5.1  1992/10/03  22:58:40  syd
  62.  * Initial checkin as of 2.4 Release at PL0
  63.  *
  64.  *
  65.  ******************************************************************************/
  66.  
  67. /** Library of functions dealing with the alias system...
  68.  
  69.  **/
  70.  
  71. #include "headers.h"
  72. #include "s_elm.h"
  73. #include <ctype.h>
  74.  
  75. char *get_alias_address(), *qstrpbrk();
  76. extern int current_mail_message;
  77.  
  78. /*
  79.  * Expand "name" as an alias and return a pointer to static data containing
  80.  * the expansion.  If "name" is not an alias, then NULL is returned.
  81.  */
  82. char *get_alias_address(name, mailing, too_longp)
  83. char *name;    /* name to expand as an alias                */
  84. int mailing;    /* TRUE to fully expand group names & recursive aliases    */
  85. int *too_longp;    /* error code if expansion overflows buffer        */
  86. {
  87.     static char buffer[VERY_LONG_STRING];
  88.     char *bufptr;
  89.     int bufsize, are_in_aliases = TRUE;
  90.  
  91.     if (!inalias) {
  92.         main_state();
  93.         are_in_aliases = FALSE;
  94.     }
  95. /*
  96.  *    Reopens files iff changed since last read
  97.  */
  98.     open_alias_files(are_in_aliases);
  99. /*
  100.  *    If name is an alias then return its expansion
  101.  */
  102.     bufptr = buffer;
  103.     bufsize = sizeof(buffer);
  104.     if (do_get_alias(name,&bufptr,&bufsize,mailing,FALSE,0,too_longp)) {
  105.     /*
  106.      *  Skip comma/space from add_name_to_list()
  107.      */
  108.         bufptr = buffer+2;
  109.     }
  110.     else {
  111.     /*
  112.      *  Nope...not an alias (or it was too long to expand)
  113.      */
  114.         dprint(2, (debugfile,
  115.         "Could not expand alias in get_alias_address()%s\n",
  116.         *too_longp ? "\t...alias buffer overflowed." : ""));
  117.         bufptr = NULL;
  118.     }
  119.  
  120.     if (! are_in_aliases)
  121.         main_state();
  122.  
  123.     return(bufptr);
  124. }
  125.  
  126.  
  127. /*
  128.  * Determine if "name" is an alias, and if so expand it and store the result in
  129.  * "*bufptr".  TRUE returned if any expansion occurs, else FALSE is returned.
  130.  */
  131. int do_get_alias(name, bufptr, bufsizep, mailing, sysalias, depth, too_longp)
  132. char *name;    /* name to expand as an alias                */
  133. char **bufptr;    /* place to store result of expansion            */
  134. int *bufsizep;    /* available space in the buffer            */
  135. int mailing;    /* TRUE to fully expand group names & recursive aliases    */
  136. int sysalias;    /* TRUE to suppress checks of the user's aliases    */
  137. int depth;    /* recursion depth - initially call at depth=0        */
  138. int *too_longp;    /* error code if expansion overflows buffer        */
  139. {
  140.     struct alias_rec *match;
  141.     char abuf[VERY_LONG_STRING];
  142.     int loc;
  143.  
  144.     /* update the recursion depth counter */
  145.     ++depth;
  146.  
  147.     dprint(6, (debugfile, "%*s->attempting alias expansion on \"%s\"\n",
  148.         (depth*2), "", name));
  149.  
  150.     /* strip out (comments) and leading/trailing whitespace */
  151.     remove_possible_trailing_spaces( name = strip_parens(name) );
  152.     for ( ; isspace(*name)  ; ++name ) ;
  153.  
  154.     /* throw back empty addresses */
  155.     if ( *name == '\0' )
  156.       return FALSE;
  157.  
  158. /* The next two blocks could be merged somewhat */
  159.     /* check for a user alias, unless in the midst of sys alias expansion */
  160.     if ( !sysalias ) {
  161.       if ( (loc = find_alias(name, USER)) >= 0 ) {
  162.         match = aliases[loc];
  163.         strcpy(abuf, match->address);
  164.         if ( match->type & PERSON ) {
  165.           if (strlen(match->name) > 0) {
  166.                 sprintf(abuf+strlen(abuf), " (%s)", match->name);
  167.           }
  168.         }
  169.         goto do_expand;
  170.       }
  171.     }
  172.  
  173.     /* check for a system alias */
  174.       if ( (loc = find_alias(name, SYSTEM)) >= 0 ) {
  175.         match = aliases[loc];
  176.         strcpy(abuf, match->address);
  177.         if ( match->type & PERSON ) {
  178.           if (strlen(match->name) > 0) {
  179.                 sprintf(abuf+strlen(abuf), " (%s)", match->name);
  180.           }
  181.         }
  182.         sysalias = TRUE;
  183.         goto do_expand;
  184.       }
  185.  
  186.     /* nope...this name wasn't an alias */
  187.     return FALSE;
  188.  
  189. do_expand:
  190.  
  191.     /* at this point, alias is expanded into "abuf" - now what to do... */
  192.  
  193.     dprint(7, (debugfile, "%*s  ->expanded alias to \"%s\"\n",
  194.         (depth*2), "", abuf));
  195.  
  196.     /* check for an exact match */
  197.     loc = strlen(name);
  198.     if ( strncmp(name, abuf, loc) == 0 &&
  199.          (isspace(abuf[loc]) || abuf[loc] == '\0') ) {
  200.       if (add_name_to_list(abuf, bufptr, bufsizep)) {
  201.           return TRUE;
  202.       }
  203.       else {
  204.           *too_longp = TRUE;
  205.           return FALSE;
  206.       }
  207.     }
  208.  
  209.     /* see if we are stuck in a loop */
  210.     if ( depth > 12 ) {
  211.       dprint(2, (debugfile,
  212.           "alias expansion loop detected at \"%s\" - bailing out\n", name));
  213.         error1(catgets(elm_msg_cat, ElmSet, ElmErrorExpanding,
  214.         "Error expanding \"%s\" - probable alias definition loop."),
  215.         name);
  216.         return FALSE;
  217.     }
  218.  
  219.     /* see if the alias equivalence is a group name */
  220.     if ( mailing && match->type & GROUP )
  221.       return do_expand_group(abuf,bufptr,bufsizep,sysalias,depth,too_longp);
  222.  
  223.     /* see if the alias equivalence is an email address */
  224.     if ( qstrpbrk(abuf,"!@:") != NULL ) {
  225.         if (add_name_to_list(abuf, bufptr, bufsizep)) {
  226.             return TRUE;
  227.         }
  228.         else {
  229.             *too_longp = TRUE;
  230.             return FALSE;
  231.         }
  232.     }
  233.  
  234.     /* see if the alias equivalence is itself an alias */
  235.     if ( mailing &&
  236.          do_get_alias(abuf,bufptr,bufsizep,TRUE,sysalias,depth,too_longp) )
  237.       return TRUE;
  238.  
  239.     /* the alias equivalence must just be a local address */
  240.     if (add_name_to_list(abuf, bufptr, bufsizep)) {
  241.         return TRUE;
  242.     }
  243.     else {
  244.         *too_longp = TRUE;
  245.         return FALSE;
  246.     }
  247. }
  248.  
  249.  
  250. /*
  251.  * Expand the comma-delimited group of names in "group", storing the result
  252.  * in "*bufptr".  Returns TRUE if expansion occurs OK, else FALSE in the
  253.  * event of errors.
  254.  */
  255. int do_expand_group(group, bufptr, bufsizep, sysalias, depth, too_longp)
  256. char *group;    /* group list to expand                    */
  257. char **bufptr;    /* place to store result of expansion            */
  258. int *bufsizep;    /* available space in the buffer            */
  259. int sysalias;    /* TRUE to suppress checks of the user's aliases    */
  260. int depth;    /* nesting depth                    */
  261. int *too_longp;    /* error code if expansion overflows buffer        */
  262. {
  263.     char *name, *gecos;
  264.     char expanded_address[LONG_STRING];
  265.     extern char *get_full_name();
  266.  
  267.     /* go through each comma-delimited name in the group */
  268.     while ( group != NULL ) {
  269.  
  270.       /* extract the next name from the list */
  271.       for ( name = group ; isspace(*name) ; ++name ) ;
  272.       if ( (group = index(name,',')) != NULL )
  273.           *group++ = '\0';
  274.       remove_possible_trailing_spaces(name);
  275.       if ( *name == '\0' )
  276.         continue;
  277.  
  278.       /* see if this name is really an alias */
  279.       if (do_get_alias(name,bufptr,bufsizep,TRUE,sysalias,depth,too_longp))
  280.         continue;
  281.  
  282.       if ( *too_longp )
  283.           return FALSE;
  284.  
  285.       /* verify it is a valid address */
  286.       if ( valid_name(name) ) {
  287.         gecos = get_full_name(name);
  288.  
  289.         if (gecos && (strlen(gecos) > 0)) {
  290.             sprintf(expanded_address, "%s (%s)", name, gecos);
  291.             name = expanded_address;
  292.         }
  293.       }
  294.  
  295.       /* add it to the list */
  296.       if ( !add_name_to_list(name, bufptr, bufsizep) ) {
  297.         *too_longp = TRUE;
  298.         return FALSE;
  299.       }
  300.  
  301.     }
  302.  
  303.     return TRUE;
  304. }
  305.  
  306.  
  307. /*
  308.  * Append "<comma><space>name" to the list, checking to ensure the buffer
  309.  * does not overflow.  Upon return, *bufptr and *bufsizep will be updated to
  310.  * reflect the stuff added to the buffer.  If a buffer overflow would occur,
  311.  * an error message is printed and FALSE is returned, else TRUE is returned.
  312.  */
  313. int add_name_to_list(name,bufptr,bufsizep)
  314. register char *name;    /* name to append to buffer            */
  315. register char **bufptr;    /* pointer to pointer to end of buffer        */
  316. register int *bufsizep;    /* pointer to space remaining in buffer        */
  317. {
  318.     if ( *bufsizep < 0 )
  319.         return FALSE;
  320.  
  321.     *bufsizep -= strlen(name)+2;
  322.     if ( *bufsizep <= 0 ) {
  323.         *bufsizep = -1;
  324.         dprint(2, (debugfile,
  325.         "Alias expansion is too long in add_name_to_list()\n"));
  326.         error(catgets(elm_msg_cat, ElmSet, ElmAliasExpTooLong,
  327.         "Alias expansion is too long."));
  328.         return FALSE;
  329.     }
  330.  
  331.     *(*bufptr)++ = ',';
  332.     *(*bufptr)++ = ' ';
  333.     while ( *name != '\0' )
  334.       *(*bufptr)++ = *name++ ;
  335.     **bufptr = '\0';
  336.  
  337.     return TRUE;
  338. }
  339.